/*
 * @Author: gk
 * @Date:   2019-01-21 14:57:47
 * @Last Modified by:   gk
 * @Last Modified time: 2019-10-17 16:09:18
 */

function PublicFunction() {
    this.watchTarget = {}; //发布中心 收发机制使用
};

/**
 * 
 * 时间
 * 
 */

Date.prototype.format = function (format) { //给时间添加一个处理时间格式的函数
    var date = {
        "M+": this.getMonth() + 1,
        "d+": this.getDate(),
        "h+": this.getHours(),
        "m+": this.getMinutes(),
        "s+": this.getSeconds(),
        "q+": Math.floor((this.getMonth() + 3) / 3),
        "S+": this.getMilliseconds()
    };
    if (/(y+)/i.test(format)) {
        format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length))
    }
    for (var k in date) {
        if (new RegExp("(" + k + ")").test(format)) {
            format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? date[k] : ("00" + date[k]).substr(("" + date[k]).length))
        }
    }
    return format
};

PublicFunction.prototype.getNowFormatDateAfter = function (AddDayCount, date) { //获取AddDayCount天后的日期
    var oDate = date ? this.getTimeFormat(date) : new Date();
    oDate.setDate(oDate.getDate() + AddDayCount);
    return oDate;
};

PublicFunction.prototype.getTimeFormat = function (date) { //兼容ios的时间格式处理
    var oDate = date.replace(/-/g, '/').replace(/\./g, '/');
    oDate = new Date(oDate);
    return oDate;
};

PublicFunction.prototype.getTime = function (date) { //处理时间
    var oDate = date ? this.getTimeFormat(date) : new Date();
    var y = oDate.getFullYear();
    var m = oDate.getMonth() + 1;
    var d = oDate.getDate();
    var h = oDate.getHours();
    var min = oDate.getMinutes();
    var s = oDate.getSeconds();
    return {
        y: y,
        m: m,
        d: d,
        h: h,
        min: min,
        s: s
    }
};

PublicFunction.prototype.getWeek = function (departureDate) { //获取周几并判断是否为今天
    var day = departureDate ? this.getTimeFormat(departureDate) : new Date(); //将日期值格式化
    departureDate = day.format('yyyy-MM-dd');
    var today = new Date().format('yyyy-MM-dd');
    var weekday = new Array("周日", "周一", "周二", "周三", "周四", "周五", "周六"); //创建星期数组
    var tomorrow = this.getNowFormatDateAfter(1).format('yyyy-MM-dd'); //获取明天的日期
    var dopodomani = this.getNowFormatDateAfter(2).format('yyyy-MM-dd'); //获取后天的日期
    var yesterday = this.getNowFormatDateAfter(-1).format('yyyy-MM-dd'); //获取昨天的日期
    var beforeYesterday = this.getNowFormatDateAfter(-2).format('yyyy-MM-dd'); //获取前天的日期
    var obj = {};
    obj.isToday = (departureDate == today); //是否为今天
    obj.isTomorrow = (departureDate == tomorrow); //是否为明天
    obj.isDopodomani = (departureDate == dopodomani); //是否为后天
    obj.isYesterday = (departureDate == yesterday); //是否为昨天
    obj.isBeforeYesterday = (departureDate == beforeYesterday); //是否为前天
    obj.week = weekday[day.getDay()]; //周几
    obj.day = day.format('MM-dd'); //月日
    obj.time = day.format('hh:mm'); //时分
    return obj;
};

PublicFunction.prototype.isDateBetween = function (dateString, startDateString, endDateString) { //判断日期是否在设定区间内
    //参数 判断时间 开始时间 结束时间
    var flag = false;
    var startFlag = (this.dateCompare(dateString, startDateString) < 1);
    var endFlag = (this.dateCompare(dateString, endDateString) > -1);
    (startFlag && endFlag) && (flag = true);
    return flag
};

PublicFunction.prototype.dateCompare = function (dateString, compareDateString) { //判断日期的先后关系
    //结果 0为相同 1为后者大 -1为前者大
    var dateTime = this.getTimeFormat(dateString).getTime();
    var compareDateTime = this.getTimeFormat(compareDateString).getTime();
    var flag = 0;
    (compareDateTime > dateTime) && (flag = 1);
    (compareDateTime < dateTime) && (flag = -1);
    return flag;
};

PublicFunction.prototype.dateNum = function (y, m, d) { //获取该天是这一年的第几天 传入年，月，日 
    var dataOne = y + ".01.01";
    var dataTwo = y + "." + m + "." + d;
    var numOne = new Date(dataOne).getTime();
    var numTwo = new Date(dataTwo).getTime();
    day = (numTwo - numOne) / (1000 * 60 * 60 * 24);
    return day + 1;
};

/**
 * 
 * 设备信息
 * 
 */

PublicFunction.prototype.IsMove = function () { //获取设备信息安卓还是ios 
    var u = navigator.userAgent,
        app = navigator.appVersion;
    var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
    var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
    return {
        isAndroid: isAndroid,
        isiOS: isiOS,
    };
};

PublicFunction.prototype.IsPC = function () { //pc还是移动
    var userAgentInfo = navigator.userAgent;
    var Agents = ["Android", "iPhone",
        "SymbianOS", "Windows Phone",
        "iPad", "iPod"
    ];
    var flag = true;
    for (var v = 0; v < Agents.length; v++) {
        if (userAgentInfo.indexOf(Agents[v]) > 0) {
            flag = false;
            break;
        }
    }
    return flag;
};

PublicFunction.prototype.getFacilityMgs = function () { //获取设备信息
    var isMove = this.IsMove();
    return {
        isPC: this.IsPC(),
        isAndroid: isMove.isAndroid,
        isiOS: isMove.isiOS,
    };
};

/**
 *
 * 正则
 * 
 */
PublicFunction.prototype.stringEncryption = function (str, num1, num2, num3) { //手机号身份证等信息加密
    return str.replace(eval('/(\\d{' + num1 + '})\\d{' + num2 + '}(\\d{' + num3 + '})/'), '$1****$2');
};

PublicFunction.prototype.checkPhoneNum = function (val) { //手机号验证
    return /^1\d{10}$/.test(val);
};

PublicFunction.prototype.checkIDNum = function (val) { //身份证号验证
    return /^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|[xX])$/.test(val);
};

PublicFunction.prototype.checkEmail = function (val) { //邮箱验证
    return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(val);
};

/**
 *
 * 数字
 * 
 */


PublicFunction.prototype.getRandom = function (json) { // json 中的超大数字转化为字符串
    return json.replace(/([\[:])?([\d\.?\d?]{15,999})([,\}\]])/g, '$1"$2"$3')
};

PublicFunction.prototype.getRandom = function (a, b) { //获取任意范围内的随机整数
    return ~~(Math.random() * (b - a) + a);
};

PublicFunction.prototype.zeroFill = function (s) { //数字补0
    return s < 10 ? '0' + s : s
};

PublicFunction.prototype.getNumberPattern = function (number, digit) { //处理数字保留几位小数（默认保留2位）
    digit = digit || (digit === 0 ? 0 : 2)
    digit < 0 && (digit = 0)
    number = number.replace(/[^\d.]/g, "").replace(/^\./g, "").replace(/\.{2,}/g, ".").replace(".", "$#$").replace(/\./g,
        "").replace("$#$", "."); //正则处理
    //replace(/[^\d.]/g,"");  //清除“数字”和“.”以外的字符
    //replace(/^\./g,"");  //验证第一个字符是数字而不是.
    //replace(/\.{2,}/g,"."); //只保留第一个. 清除多余的.
    //replace(".","$#$").replace(/\./g,"").replace("$#$",".");
    var x = String(number).indexOf('.') + 1; //小数点的位置
    x > 0 && (number = String(number).slice(0, x + digit)); //大于2位的截取
    return number;
};

/**
 *
 *  页面参数
 * 
 */

PublicFunction.prototype.getPageString = function (name) { //获取页面相应参数
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    var r = window.location.search.substr(1).match(reg);
    return (r != null) ? unescape(r[2]) : "";
};

PublicFunction.prototype.getPageAllString = function () { //获取页面所有参数
    var mgs = {}; //参数结果
    var url = window.location.href; //获取路径得到传参
    var a = url.indexOf("?"); //根据问号得到传参的位置
    if (a > -1) {
        var b = url.substr(a + 1); //拿到参数的字符串
        var mgsArr = b.split("&"); //改写为一个数组
        mgsArr.forEach(function (val) { //遍历
            var index = val.indexOf("=");
            mgs[val.substring(0, index)] = val.substring(index + 1, val.length);
        });
    };
    return mgs;
};

PublicFunction.prototype.getJsonToParam = function (json) { //将json转化为get路径参数
    return Object.keys(json).map((key) => {
        return encodeURIComponent(key) + '=' + encodeURIComponent(json[key] || '')
    }).join('&')
};

/**
 *
 *  其他
 * 
 */

// 判断变量的具体类型
PublicFunction.prototype.typeOf = function (obj) {
    let res = Object.prototype.toString.call(obj).split(' ')[1]
    res = res.substring(0, res.length - 1).toLowerCase()
    return res
}

//base64图片下载
/**
 * imgName 文件名
 * 
 * content 文件内容 base64图片信息
 * 
 * */

PublicFunction.prototype.downloadImg = function (imgName, content) {
    const aLink = document.createElement('a')
    const blob = this.base64ToBlob(content) // new Blob([content]);
    const evt = document.createEvent('HTMLEvents')
    evt.initEvent('click', true, true)// initEvent 不加后两个参数在FF下会报错  事件类型，是否冒泡，是否阻止浏览器的默认行为
    aLink.download = imgName
    aLink.href = URL.createObjectURL(blob)
    // aLink.dispatchEvent(evt);
    aLink.click()
},
    // base64转blob
    PublicFunction.prototype.base64ToBlob = function (code) {
        const parts = code.split(';base64,')
        const contentType = parts[0].split(':')[1]
        const raw = window.atob(parts[1])
        const rawLength = raw.length
        const uInt8Array = new Uint8Array(rawLength)
        for (let i = 0; i < rawLength; ++i) {
            uInt8Array[i] = raw.charCodeAt(i)
        }
        return new Blob([uInt8Array], { type: contentType })
    }




PublicFunction.prototype.getCombination = function (array) { //多个数组组合
    // const textArr = [
    // 	['a', 'b', 'c'],
    // 	['d', 'e', 'f', 'g'],
    // 	['h', 'i']
    // ]
    let resultArry = [];
    array.forEach((arrItem) => {
        if (resultArry.length === 0) {
            resultArry = arrItem
        } else {
            const emptyArray = [];
            resultArry.forEach((item) => {
                arrItem.forEach((value) => {
                    emptyArray.push([...item, value])
                })
            })
            resultArry = emptyArray
        }
    });
    return resultArry;
}


PublicFunction.prototype.copyText = function (text) { //复制文字（该方法无法在异步环境使用 document.execCommand不支持）
    var input = document.createElement("input");
    input.setAttribute("readonly", true); //设置只读防止ios唤起键盘
    input.value = text; //copy的文字  
    document.body.appendChild(input);
    input.select();
    input.setSelectionRange(0, input.value.length), document.execCommand('Copy');
    document.body.removeChild(input);
};

PublicFunction.prototype.idCardFilter = function (num) { //身份证手机号等加密--大于16位的必须传字符串
    (typeof num == "String") || (num = String(num));
    var length = num.length;
    var str = "";
    for (var i = 0; i < length - 7; i++) {
        str += "*"
    };
    return num.substring(0, 3) + str + num.substring(num.length - 4, num.length);
};

PublicFunction.prototype.getIDNumber = function (str) { //输入前17位计算第18位返回身份证号
    var arr = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; //系数
    var lastNumArr = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2]; //对应数
    var numArr = str.split("");
    var allNum = 0;
    arr.forEach((val, key) => {
        allNum += val * numArr[key];
    });
    var lastNum = lastNumArr[allNum % 11];
    str.length = 17;
    var result = str + lastNum;
    return result
};

PublicFunction.prototype.preventContinuousClicked = function (that, second) { //防止连点
    //(传入this,记录时间),连点的时间间隔默认为500毫秒
    var nowTime = (new Date()).getTime();
    second || (second = 500);
    var flag = true; //true为可以点击 false为触发连点
    if (that.preventContinuousClickedTime) {
        flag = (nowTime - that.preventContinuousClickedTime) > second;
    } else {
        that.preventContinuousClickedTime = nowTime;
        var time = setTimeout(function () {
            that.preventContinuousClickedTime = null;
            clearTimeout(time); //清除延时器释放内存
        }, second);
    }
    return flag;
};

PublicFunction.prototype.countDown = function (second, that, fn) { //倒计时 （锁屏依然有效） 
	/**
	 * 1.second 传入剩余倒计时秒数
	 *
	 * 2.that (出入this,this仅为数据的存储位置，如小程序开发传入 this.data vue传入this)
	 *
	 * 3.fn 读秒结束的回调函数
	 *
	 *  将会给this上挂载一个所剩读秒的对象 名为 _countDownTime 包含分秒俩个值
	 *  that._countDownTime = {
	 *  	min:"", //分
	 *  	s:"" //秒
	 *  };
	 */
    var lastTime = (new Date()).getTime(); //记录上次的时间初始值为开始
    var residueTime = second; //记录剩余的秒数
    that._countDownTime || (that._countDownTime = {});
    var timer = setInterval(function () {
        var nowTime = (new Date()).getTime(); //获取现在的时间
        //计算时间差
        var time = (nowTime - lastTime) / 1000; //取整
        residueTime = residueTime - time; //获得剩余的秒数
        lastTime = nowTime; //更新上一个时间
        if (residueTime > 0) { //剩余的秒数转化格式
            if (that._countDownTime) {
                that._countDownTime.min = Math.floor(residueTime / 60);
                that._countDownTime.s = (residueTime % 60).toFixed(0);
                //格式化时间
                that._countDownTime.min = Number(that._countDownTime.min);
                that._countDownTime.min = (that._countDownTime.min > 9) ? that._countDownTime.min : "0" + that._countDownTime.min;
                that._countDownTime.s = (that._countDownTime.s > 9) ? that._countDownTime.s : "0" + that._countDownTime.s;
            }
        } else { //归0时
            clearInterval(timer); //清除定时器
            if (that._countDownTime) {
                that._countDownTime.min = 0;
                that._countDownTime.s = 0;
            };
            fn && fn();
        };
    }, 1000);
    return timer; //返回定时器可以在不需要的时候强制终止倒计时
};


/*********封装简易watch监听器微信小程序**********/
/**
 * 使用方法
 * 对应js引入文件  例如 var publicMethod = require("../../commentjs/public.js");
 * 在onLoad中加入如下代码激活监听器 publicMethod.setWatcher(this);
 */

PublicFunction.prototype.setWatcher = function (that) { //设置监听器 
    // 接收传过来的this对象
    Object.keys(that.watch).forEach(i => { // 将watch对象内的key遍历
        this.observe(i, that); // 监听data内的i属性，传入watch内对应函数以调用
    })
};

PublicFunction.prototype.observe = function (key, that) { //监听属性 并执行监听函数
    var val = that.data[key]; // 给该属性设默认值
    Object.defineProperty(that.data, key, {
        configurable: true,
        enumerable: true,
        set: function (value) {
            //函数接收改监听变量当前的值
            that.watch[key].call(that, value); // 赋值(set)时，调用对应函数并且修改this指针
        },
        get: function () {
            return val;
        }
    })
};



// PublicFunction.prototype.onReachBottom = function(msg) { //下拉加载封装 传入执行函数 或者 非函数解除监听
// 	var width = window.screen.width;//屏幕宽
// 	var oBody = document.getElementsByTagName("body")[0];//body
// 	function scroll(){// 判断是否滚动到底部
// 		var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;//滚动条
// 		var offsetHeight = oBody.offsetHeight * (width/750);
// 		var flag = scrollTop >= offsetHeight * 0.8;//滚动到距离底部百分之80%开始加载
// 		(flag) && (msg && msg());
// 	};
// 	//不再需要监听时卸载
// 	(typeof msg == "function") ? window.addEventListener('scroll', scroll) : window.removeEventListener('scroll',scroll);
// };

PublicFunction.prototype.onReachBottom = function (msg) { //下拉加载封装 传入执行函数 或者 非函数
    //	var oBody = document.getElementsByTagName("body")[0];//body
    this._scrollMsg = msg;
    this._scrollFunction = function () { // 判断是否滚动到底部
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //距离顶部的距离
        var windowHeight = document.documentElement.clientHeight || document.body.clientHeight; //可视区的高度
        var scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight; //滚动条总高
        var flag = scrollTop + windowHeight >= scrollHeight * 0.9;
        flag && (this._scrollMsg && this._scrollMsg());
    };
    //不再需要监听时卸载
    (typeof this._scrollMsg == "function") ? window.addEventListener('scroll', this._scrollFunction.bind(this), false) :
        window.removeEventListener('scroll', this._scrollFunction.bind(this), false);
};

PublicFunction.prototype.stopBodyScroll = function (isFixed, that) {
    //蒙层上有滑动元素，滑动后蒙层下页面随动问题处理
	/**
	 * @param {*} isFixed  //true开启蒙层 false关闭蒙层
	 * @param {*} that //传入this,存储top值
	 */
    var bodyEl = document.body;
    if (isFixed) { //开启
        that._top = window.scrollY;
        bodyEl.style.position = 'fixed';
        bodyEl.style.top = -that._top + 'px';
    } else { //关闭
        bodyEl.style.position = 'relative';
        bodyEl.style.top = '';
        window.scrollTo(0, that._top); // 回到原先的top
    }
};


PublicFunction.prototype.save = function () { //存vuex
    window.addEventListener('beforeunload', () => {
        sessionStorage.setItem("storeState", JSON.stringify(this.$store.state));
    });
    var state;
    sessionStorage.getItem("storeState") && (state = JSON.parse(sessionStorage.getItem("storeState")));
    Object.keys(state).forEach(i => {
        this.$store.state[i] = state[i];
    }, this);
};

/**
 *
 * @param {*} param
 *
 * objA 待赋值对象
 *
 * objB 赋值对象
 *
 */

PublicFunction.prototype.listAssign = function (objA, objB) { // 对象赋值
    Object.keys(objA).forEach(key => {
        objA[key] = objB[key] === undefined ? objA[key] : objB[key]
        // objA[key] = objB[key] ?? objA[key] //es10
    })
}

//简易的时间收发机制 (发布订阅模式)

PublicFunction.prototype.watchOn = function (type, fn) { //注册监听器
    this.watchTarget[type] = fn;
}

PublicFunction.prototype.watchTrigger = function (type) { //触发监听器
    this.watchTarget[type] && this.target[type](...Array.prototype.slice.call(arguments, 1));
}

PublicFunction.prototype.watchRemove = function (type) { //执行以后清除的方法；
    this.watchTarget[type] = null;
}

// 处理瀑布流数据，[1,2,3,4,5,6,7] => [1,3,5,7,2,4,6]
PublicFunction.prototype.getWaterfallList = function (list) {
    return [].concat(...(Array.from(list.reduce((total, cur, index) => {
        total[index % 2].push(cur)
        return total
    }, { 0: [], 1: [], length: 2 }))))
}

// ios微信内alert有域名解决方法
PublicFunction.prototype.getIosWeChatAlert = function () {
    var ua = window.navigator.userAgent.toLowerCase();
    if (ua.match(/MicroMessenger/i) == 'micromessenger') { //先判断是否为微信浏览器
        //重写alert方法，alert()方法重写，不能传多余参数
        window.alert = function (name) {
            var iframe = document.createElement("IFRAME");
            iframe.style.display = "none";
            iframe.setAttribute("src", 'data:text/plain');
            document.documentElement.appendChild(iframe);
            window.frames[0].window.alert(name);
            iframe.parentNode.removeChild(iframe);
        }
    }
}


//防抖节流
PublicFunction.prototype.throttle = function throttle(fn, delay) {
  let last = 0, timer = null;
  return function (...args) {
    let context = this;
    let now = new Date();
    if(now - last < delay){
      clearTimeout(timer);
      setTimeout(function() {
        last = now;
        fn.apply(context, args);
      }, delay);
    } else {
      // 这个时候表示时间到了，必须给响应
      last = now;
      fn.apply(context, args);
    }
  }
}

PublicFunction.prototype.compareVersion = function(a, b) {
    let stringA = a.split(".").join("")
    let stringB = b.split(".").join("")
    let flag = stringA.length > stringB.length;
    let res; // 0相等 1后者大 -1前者大
    if (flag) {
        let resA = stringA.slice(0, stringB.length)
        if (Number(resA) === Number(stringB)) {
            let other = stringA.slice(stringB.length, stringA.length)
            res = Number(other) == 0 ? 0 : -1
        } else {
            res = Number(resA) > Number(stringB) ? -1 : 1
        }
    } else {
        let resB = stringB.slice(0, stringA.length)
        if (Number(resB) === Number(stringA)) {
            let other = stringB.slice(stringA.length, stringB.length)
            res = Number(other) == 0 ? 0 : 1
        } else {
            res = Number(resB) > Number(stringA) ? 1 : -1
        }
    }
    return res
}

// 将内容复制到剪贴板
const copyToClipboard = (content) => navigator.clipboard.writeText(content)

// . 获取鼠标选中内容
const getSelectedText = () => window.getSelection().toString()

// 打乱一个数组
const shuffleArray = array => array.sort(() => Math.random() - 0.5)

// 将rgba转换为十六进制
const rgbaToHex = (r, g, b) => "#" + [r, g, b].map(num => parseInt(num).toString(16).padStart(2, '0')).join('')

// .将十六进制转换为rgba
const hexToRgba = hex => {
  const [r, g, b] = hex.match(/\w\w/g).map(val => parseInt(val, 16))
  return `rgba(${r}, ${g}, ${b}, 1)`;
}

//获取多个数字的平均值 
const average = (...args) => args.reduce((a, b) => a + b, 0) / args.length

// 检查一个数字是偶数还是奇数
const isEven = num => num % 2 === 0

// 在数组中去重元素
const uniqueArray = (arr) => [...new Set(arr)]

// 检查一个对象是否为空对象
const isEmpty = obj => Reflect.ownKeys(obj).length === 0 && obj.constructor === Object

// 反转字符串
const reverseStr = str => str.split('').reverse().join('')

// 计算两个日期之间的间隔
const dayDiff = (d1, d2) => Math.ceil(Math.abs(d1.getTime() - d2.getTime()) / 86400000)

// 找出日期所在的年份中的天数
const dayInYear = (d) => Math.floor((d - new Date(d.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24)

// 将字符串的首字母大写
const capitalize = str => str.charAt(0).toUpperCase() + str.slice(1)

// 生成指定长度的随机字符串
const generateRandomString = length => [...Array(length)].map(() => Math.random().toString(36)[2]).join('')

// 在两个整数之间获取一个随机整数
const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min)

// 指定位数四舍五入
const round = (n, d) => Number(Math.round(n + "e" + d) + "e-" + d)

// 清除所有的cookies
const clearCookies = document.cookie.split(';').forEach(cookie => document.cookie = cookie.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date(0).toUTCString()};path=/`))

// 检测是否为暗黑模式
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches

// 滚动到页面顶部
const goToTop = () => window.scrollTo(0, 0)

// 判断是否为苹果设备
const isAppleDevice = () => /Mac|iPod|iPhone|iPad/.test(navigator.platform)

// 随机布尔值
const randomBoolean = () => Math.random() >= 0.5

// 获取变量的类型
const typeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase()

// 判断当前选项卡是否处于活动状态
const checkTabInView = () => !document.hidden

// 检查元素是否处于焦点状态
const isFocus = (ele) => ele === document.activeElement

// 随机IP
const generateRandomIP = () => {
  return Array.from({length: 4}, () => Math.floor(Math.random() * 256)).join('.');
}

var publicMethod = new PublicFunction();


//Array.prototype.slice.call(arguments,1); //对象使用数组的方法
